home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr48 / sprites.zip / SPRITES.PAS < prev    next >
Pascal/Delphi Source File  |  1993-04-14  |  15KB  |  504 lines

  1. unit Sprites;
  2. { Basically a simple and effective spriteengine for use with Turbo }
  3. { Pascal 6.0. (Does not require the GRAPH unit..)                  }
  4. {                                                                  }
  5. { Designed for use with MCGA, VGA and compatibles. Works in mode   }
  6. { mode $13 (320x200 with 256 simultaneously colours.               }
  7. {                                                                  }
  8. { Written by:                                                      }
  9. {            Marius Kjeldahl                                       }
  10. {            Stud. post 104                                        }
  11. {            N-7034 Trondheim - NTH                                }
  12. {            Norway                                                }
  13. {            Ph. +47 7 58 91 11                                    }
  14. {            e-mail: mariusk@lise.unit.no                          }
  15. {                    (at NTH - Norwegian Institute of Technology ) }
  16. {                    (dept. of Business and Information Technolgy) }
  17. {                                                                  }
  18. { These routines are being distributed as shareware. To be used in,}
  19. { or as part of any commercial product, you have to become a       }
  20. { registered user. As a registered user you will receive upgrades  }
  21. { and rights to distribute these routines with your products.      }
  22. { To become a registered user, you will have to send a letter with }
  23. { who you are and what product(s) will use these routines and      }
  24. { make US$39 payable to the author (cheque or money..).            }
  25. {                                                                  }
  26. {                                                                  }
  27. { If you have any suggestions or comments please do not hesitate   }
  28. { to contact me. Have fun...                                       }
  29. {                                                                  }
  30. { Future plans for enhancements: interrupt driven, faster rep      }
  31. { movsw for sprites, built in animation, screen region scrolling   }
  32. { and more..                                                       }
  33.  
  34. interface
  35. uses
  36.   Dos;
  37. const
  38.   MaxSprites = 14; { Maximum number of sprites activated simultaneously }
  39.   MaxDim = 25*25;  { Dimensions of largest sprite to be used (x*y)      }
  40. type
  41.   ScreenTypePointer = ^ScreenType;       { Pointer to a virtual screen  }
  42.   ScreenType = array [1..64000] of byte; { Array to hold virtual screen }
  43.   SpriteType = record                    { Misc. sprite data            }
  44.                  oldx, oldy,             { - old location               }
  45.                  x, y : integer;         { - current location           }
  46.                  w, h : byte;            { - width and height           }
  47.                  SpriteData,             { - spriteimage                }
  48.                  Buffer : array [0..MaxDim-1] of byte; { spritebackgr.  }
  49.                  Active : boolean;       { - currently active           }
  50.                  ix, iy : integer;       { - sprite increment           }
  51.                                          {   (not currently used)       }
  52.                end;
  53. var
  54.   Sprite : array [1..MaxSprites] of SpriteType; { Array of sprites      }
  55.   Virtual_Screen : ScreenTypePointer;    { Pointer to virtual screen    }
  56.  
  57.   procedure DrawSprites;
  58.   { Saves background and draws all currently active sprites at their    }
  59.   { current location.                                                   }
  60.  
  61.   procedure LoadSprite (Num : byte; FileName : string);
  62.   { Loads spritedata from ordinary text file. Examine the .SPR files    }
  63.   { for further details. Use .CEL files instead if you've have          }
  64.   { purchased AutoDesk Animator...                                      }
  65.  
  66.   procedure SetMode (Mode : word);
  67.   { Sets screen mode. Use $13 for use with sprites                      }
  68.  
  69.   procedure ShowVirtualScreen ;
  70.   { Copies the VirtualScreen to the users screen. Any changes done with }
  71.   { the sprites and/or their position will NOT be visible until this    }
  72.   { routine has been called!                                            }
  73.  
  74.   procedure LoadCOL (FileName : string);
  75.   { Loads a file containing the palette desc. of the 256 colours and    }
  76.   { programs the VGA/MCGA to use these palette. It uses AutoDesk        }
  77.   { Animators file format - so you can use Animator to select colors and}
  78.   { then save the palette in Animators ordinary .COL file.              }
  79.   { For those without Animator (you should not be..) the file format is }
  80.   { simple. Each colour (from 0 to 255) has three bytes which containts }
  81.   { red, green and blue values. First in the file comes (usually)       }
  82.   { 0,0,0 - black and so on until the last colour.                      }
  83.  
  84.   procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  85.   { Directly loads a CEL to the location pointed to by ScrPtr.          }
  86.   { This routine uses AutoDesk Animators file format. This means you    }
  87.   { can use Animators excellent drawing tools to design you sprites and }
  88.   { save them in a ordinary .CEL file.                                  }
  89.   { For those without Animator; here is a short desc. of the format:    }
  90.   { The first 800 bytes is Animators header. It does include various    }
  91.   { information like it's own colours palette, width and height.        }
  92.   { However this version skips all that information and just reads the  }
  93.   { image data into the location pointed to by ScrPtr. Remember to      }
  94.   { set the sprites width and height too! (It is NOT read you of the    }
  95.   { .CEL file in this release..                                         }
  96.  
  97.   procedure DisableAllSprites;
  98.   { Disables all sprites. But this routine does not restore the screen  }
  99.   { image (compare with HideSprites..                                   }
  100.  
  101.   procedure HideSprites;
  102.   { Disables all sprites. Basically same as DisableAllSprites, but this }
  103.   { routine also recovers the "original" screen image.                  }
  104.  
  105.   procedure FillBox (x1, y1, x2, y2 : integer; b : byte);
  106.   { Draws a coloured box with upper left corner x1,y1 and lower right   }
  107.   { corner x2,y2.                                                       }
  108.  
  109.   procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer);
  110.   { "Stamps" a copy of any sprite at the chosen location x1,y1.         }
  111.   { Use this routine if you want to put the image there, but do not plan}
  112.   { to animate in anyway..                                              }
  113.  
  114.   procedure WaitForVerticalRetrace;
  115.   { Waits for vertical retrace. Will be used in further releases..      }
  116.  
  117. implementation
  118.  
  119. procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer); assembler;
  120. label
  121.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  122.   asm
  123.     push  ds
  124.     push  es
  125.     lds   si,Sprite
  126.     mov   ax,x1     { ax = x }
  127.     mov   bx,y1     { bx = y }
  128. _Redraw:
  129.     push  ax
  130.     push  bx
  131.     mov   ax,word(Virtual_Screen+2)
  132.     mov   es,ax         { ES=A000h }
  133.     pop   bx            { ax = y }
  134.     mov   ax,320
  135.     mul   bx            { ax = y * 320 }
  136.     pop   bx            { ax = x }
  137.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  138.     mov   di,ax         { di = skjermadr. }
  139.     mov   dl,[si+9]     { dl = height of sprite }
  140.     xor   ch,ch
  141.     mov   cl,[si+8]     { cx = width of sprite }
  142.     add   si,10         { si = start of spritedata }
  143.     cld
  144. _DrawLoop:
  145.     push  di            { store y adr. for later }
  146.     push  cx            { store width }
  147. _LineLoop:
  148.     mov   bl,byte ptr [si]
  149.     or    bl,bl
  150.     jnz   _Store
  151. _NoPaint:
  152.     inc    si
  153.     inc    di
  154.     loop   _LineLoop
  155.     jmp    _NextLine
  156. _Store:
  157. {    test   byte ptr [es:di],1
  158.     jz     _NoPaint}
  159.     movsb
  160.     loop  _LineLoop
  161. _NextLine:
  162.     pop   cx
  163.     pop   di
  164.     dec   dl
  165.     jz    _Exit
  166.     add   di,320        { di = next line of sprite }
  167.     jmp   _DrawLoop
  168. _Exit:
  169.     pop   es
  170.     pop   ds
  171.   end;
  172.  
  173. procedure DrawSprite (var Sprite : SpriteType); assembler;
  174. label
  175.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  176.   asm
  177.     push  ds
  178.     push  es
  179.     lds   si,Sprite
  180.     mov   ax,[si+4]     { ax = x }
  181.     mov   bx,[si+6]     { bx = y }
  182.     {cmp   ax,[si]        if x <> oldx then _Redraw
  183.     jne   _Redraw
  184.     cmp   bx,[si+2]
  185.     je    _Exit}         { if (x=oldx) and (y=oldy) then exit }
  186. _Redraw:
  187.     mov   [si],ax       { oldx = x }
  188.     mov   [si+2],bx     { oldy = y }
  189.     push  ax
  190.     push  bx
  191.     mov   ax,word(Virtual_Screen+2)
  192.     mov   es,ax         { ES=A000h }
  193.     pop   bx            { ax = y }
  194.     mov   ax,320
  195.     mul   bx            { ax = y * 320 }
  196.     pop   bx            { ax = x }
  197.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  198.     mov   di,ax         { di = skjermadr. }
  199.     mov   dl,[si+9]     { dl = height of sprite }
  200.     xor   ch,ch
  201.     mov   cl,[si+8]     { cx = width of sprite }
  202.     add   si,10         { si = start of spritedata }
  203.     cld
  204. _DrawLoop:
  205.     push  di            { store y adr. for later }
  206.     push  cx            { store width }
  207. _LineLoop:
  208.     mov   bl,byte ptr [si]
  209.     or    bl,bl
  210.     jnz   _Store
  211. _NoPaint:
  212.     inc    si
  213.     inc    di
  214.     loop   _LineLoop
  215.     jmp    _NextLine
  216. _Store:
  217. {    test   byte ptr [es:di],1
  218.     jz     _NoPaint}
  219.     movsb
  220.     loop  _LineLoop
  221. _NextLine:
  222.     pop   cx
  223.     pop   di
  224.     dec   dl
  225.     jz    _Exit
  226.     add   di,320        { di = next line of sprite }
  227.     jmp   _DrawLoop
  228. _Exit:
  229.     pop   es
  230.     pop   ds
  231.   end;
  232.  
  233. procedure SaveSpriteBackground (var Sprite : Spritetype); assembler;
  234. label
  235.   _Redraw, _DrawLoop, _Exit;
  236.   asm
  237.     push  ds
  238.     push  es
  239.     les   di,Sprite
  240.     mov   ax,es:[di+4]     { ax = x }
  241.     mov   bx,es:[di+6]     { bx = y }
  242.     push  ax
  243.     push  bx
  244.     mov   ax,word(Virtual_Screen+2)
  245.     mov   ds,ax         { DS=A000h }
  246.     pop   bx            { bx = y }
  247.     mov   ax,320
  248.     mul   bx            { ax = y * 320 }
  249.     pop   bx            { bx = x }
  250.     add   ax,bx         { ax = ax + bx dvs. skjermadr.. }
  251.     mov   si,ax         { si = skjermadr. }
  252.     mov   dl,es:[di+9]     { dl = height of sprite }
  253.     xor   ch,ch
  254.     mov   cl,es:[di+8]     { cx = width of sprite }
  255.     add   di,10+MaxDim  { di = start of screenbuffer }
  256.     cld
  257. _DrawLoop:
  258.     push  si            { store y adr. for later }
  259.     push  cx            { store width }
  260.     rep   movsb
  261.     pop   cx
  262.     pop   si
  263.     dec   dl
  264.     jz    _Exit
  265.     add   si,320        { di = next line of sprite }
  266.     jmp   _DrawLoop
  267. _Exit:
  268.     pop   es
  269.     pop   ds
  270.   end;
  271.  
  272. procedure FillBox (x1, y1, x2, y2 : integer; b : byte); assembler;
  273. label
  274.   _l1;
  275. asm
  276.   push  ds
  277.   push  es
  278.   mov   ax,word(Virtual_Screen+2)
  279.   mov   es,ax
  280.   mov   ax,y1
  281.   mov   bx,320
  282.   mul   bx
  283.   mov   di,ax
  284.   add   di,x1
  285.   mov   ax,y1
  286.   mov   dx,y2
  287.   sub   dx,ax
  288.   inc   dx
  289.  
  290.   mov   ax,x1
  291.   mov   cx,x2
  292.   sub   cx,ax { cx contains number of bytes across }
  293.   inc   cx
  294.   mov   al,b
  295.   cld
  296. _l1:
  297.   push  di
  298.   push  cx
  299.   rep   stosb
  300.   pop   cx
  301.   pop   di
  302.   add   di,320
  303.   dec   dx
  304.   jnz   _l1
  305.   pop   es
  306.   pop   ds
  307. end;
  308.  
  309.  
  310. procedure RestoreSpriteBackground (var Sprite : Spritetype); assembler;
  311. label
  312.   _Redraw, _DrawLoop, _Exit, _LineLoop;
  313.   asm
  314.     push  ds
  315.     push  es
  316.     lds   si,Sprite
  317.     mov   ax,[si]     { ax = x }
  318.     mov   bx,[si+2]     { bx = y }
  319.     push  ax
  320.     push  bx
  321.     mov   ax,word(Virtual_Screen+2)
  322.     mov   es,ax         { ES=A000h }
  323.     pop   bx            { ax = y }
  324.     mov   ax,320
  325.     mul   bx            { ax = y * 320 }
  326.     pop   bx            { ax = x }
  327.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  328.     mov   di,ax         { di = skjermadr. }
  329.     mov   dl,[si+9]     { dl = height of sprite }
  330.     xor   ch,ch
  331.     mov   cl,[si+8]     { cx = width of sprite }
  332.     add   si,10+MaxDim         { si = start of spritedata }
  333.     cld
  334. _DrawLoop:
  335.     push  di            { store y adr. for later }
  336.     push  cx            { store width }
  337.     rep   movsb
  338.     pop   cx
  339.     pop   di
  340.     dec   dl
  341.     jz    _Exit
  342.     add   di,320        { di = next line of sprite }
  343.     jmp   _DrawLoop
  344. _Exit:
  345.     pop   es
  346.     pop   ds
  347.   end;
  348.  
  349. procedure DrawSprites;
  350. var
  351.   I : byte;
  352. begin
  353.   for I := MaxSprites downto 1 do
  354.     if (Sprite[I].Active) and (Sprite [I].oldx <> -1) then
  355.       RestoreSpriteBackground (Sprite [I]);
  356.   for I := 1 to MaxSprites do begin
  357.     if Sprite [I].Active then begin
  358.       SaveSpriteBackground (Sprite [I]);
  359.       DrawSprite (Sprite [I]);
  360.     end;
  361.   end;
  362. end;
  363.  
  364. procedure HideSprites;
  365. var
  366.   I : byte;
  367. begin
  368.   for I := MaxSprites downto 1 do
  369.     if (Sprite [I].oldx <> -1) then begin
  370.       RestoreSpriteBackground (Sprite [I]);
  371.       Sprite [I].oldx := -1;
  372.     end;
  373. end;
  374.  
  375. procedure SetMode (Mode : word);
  376. begin
  377.   asm
  378.     mov ax,Mode;
  379.     int 10h
  380.   end;
  381. end;
  382.  
  383. procedure LoadSprite (Num : byte; FileName : string);
  384. var
  385.   Fil : text;
  386.   fx, fy : word;
  387. begin
  388.   assign (Fil, FileName);
  389.   reset (Fil);
  390.   fillchar (Sprite [Num], sizeof (Sprite[1]), 0);
  391.   with Sprite [Num] do begin
  392.     oldx := integer ($FFFF);
  393.     readln (Fil, w, h);          {integer-32768}
  394.     for fy := 1 to h do begin
  395.       for fx := 1 to w do
  396.         read (Fil, SpriteData [pred (fy) * w + pred (fx)]);
  397.       readln (fil);
  398.     end;
  399.   end;
  400.   close (Fil);
  401. end;
  402.  
  403. procedure LoadCOL (FileName : string);
  404. type
  405.   DACType = array [0..255] of record
  406.                                 R, G, B : byte;
  407.                               end;
  408. var
  409.   DAC : DACType;
  410.   Fil : file of DACType;
  411.   I : integer;
  412.   Regs : Registers;
  413. begin
  414.   assign (Fil, FileName);
  415.   reset (Fil);
  416.   read (Fil, DAC);
  417.   close (Fil);
  418.   for I := 0 to 255 do begin
  419.     with Regs do begin
  420.       AX := $1010;
  421.       BX := I;
  422.       DH := DAC [I].R;
  423.       CH := DAC [I].G;
  424.       CL := DAC [I].B;
  425.     end;
  426.     Intr ($10, Regs);
  427.   end;
  428. end;
  429.  
  430. procedure WaitForVerticalRetrace; assembler;
  431. label
  432.   l1, l2;
  433. asm
  434.     cli
  435.     mov dx,3DAh
  436. l1:
  437.     in al,dx
  438.     and al,08h
  439.     jnz l1
  440. l2:
  441.     in al,dx
  442.     and al,08h
  443.     jz  l2
  444.     sti
  445. end;
  446.  
  447. procedure ShowVirtualScreen; assembler;
  448.     asm
  449.       push ds
  450.       push es
  451.       xor  si,si
  452.       xor  di,di
  453.       cld
  454.       mov  ax,word(Virtual_Screen+2)
  455.       mov  ds,ax
  456.       mov  ax,0A000h
  457.       mov  es,ax
  458.       mov  cx,7D00h
  459.       rep  movsw
  460.       pop  es
  461.       pop  ds
  462.     end;
  463.  
  464. procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  465. var
  466.   Fil : file;
  467.   Buf : array [1..1024] of byte;
  468.   BlocksRead, Count : word;
  469. begin
  470.   assign (Fil, FileName);
  471.   reset (Fil, 1);
  472.   BlockRead (Fil, Buf, 800);
  473.   Count := 0; BlocksRead := $FFFF;
  474.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  475.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  476.     Count := Count + 1024;
  477.   end;
  478.   close (Fil);
  479. end;
  480.  
  481. procedure DisableAllSprites;
  482. var
  483.   I : integer;
  484. begin
  485.   for I := 1 to MaxSprites do
  486.     with Sprite [I] do begin
  487.       OldX := -1;
  488.       Active := FALSE;
  489.     end;
  490. end;
  491.  
  492. var
  493.   Dum : ^byte;
  494. begin
  495.   DisableAllSprites;
  496.   repeat
  497.     new (Virtual_Screen);
  498.     if ofs (Virtual_Screen^) <> 0 then begin
  499.       dispose (Virtual_Screen);
  500.       new (Dum);
  501.     end;
  502.   until ofs (Virtual_Screen^) = 0;
  503. end.
  504.